import { ref, computed, onMounted, onUnmounted, nextTick, readonly, type Ref } from 'vue'
import { useResponsive } from './useResponsive'

export interface PerformanceMetrics {
  fps: number
  memoryUsage: number
  loadTime: number
  renderTime: number
  networkLatency: number
}

export interface LazyLoadOptions {
  rootMargin?: string
  threshold?: number
  once?: boolean
}

/**
 * 性能监控组合式函数
 */
export function usePerformance() {
  const { isMobile, networkStatus, connectionType } = useResponsive()
  
  const metrics = ref<PerformanceMetrics>({
    fps: 0,
    memoryUsage: 0,
    loadTime: 0,
    renderTime: 0,
    networkLatency: 0
  })

  const isLowPerformance = computed(() => {
    return metrics.value.fps < 30 || 
           metrics.value.memoryUsage > 50 || 
           connectionType.value === 'slow-2g' ||
           connectionType.value === '2g'
  })

  // FPS监控
  let frameCount = 0
  let lastTime = performance.now()
  let animationFrame: number

  const measureFPS = () => {
    frameCount++
    const now = performance.now()
    
    if (now >= lastTime + 1000) {
      metrics.value.fps = Math.round((frameCount * 1000) / (now - lastTime))
      frameCount = 0
      lastTime = now
    }
    
    animationFrame = requestAnimationFrame(measureFPS)
  }

  // 内存使用监控
  const measureMemory = () => {
    // @ts-ignore - memory API 还在实验阶段
    if (performance.memory) {
      // @ts-ignore
      const { usedJSHeapSize, totalJSHeapSize } = performance.memory
      metrics.value.memoryUsage = Math.round((usedJSHeapSize / totalJSHeapSize) * 100)
    }
  }

  // 网络延迟测试
  const measureNetworkLatency = async () => {
    try {
      const start = performance.now()
      await fetch('/api/ping', { method: 'HEAD' })
      const end = performance.now()
      metrics.value.networkLatency = Math.round(end - start)
    } catch {
      metrics.value.networkLatency = -1
    }
  }

  // 页面加载时间
  const measureLoadTime = () => {
    const navigation = performance.getEntriesByType('navigation')[0] as PerformanceNavigationTiming
    if (navigation) {
      metrics.value.loadTime = Math.round(navigation.loadEventEnd - navigation.fetchStart)
    }
  }

  // 渲染时间
  const measureRenderTime = () => {
    const paintEntries = performance.getEntriesByType('paint')
    const fcp = paintEntries.find(entry => entry.name === 'first-contentful-paint')
    if (fcp) {
      metrics.value.renderTime = Math.round(fcp.startTime)
    }
  }

  onMounted(() => {
    measureFPS()
    measureLoadTime()
    measureRenderTime()
    
    // 定期更新内存和网络指标
    const interval = setInterval(() => {
      measureMemory()
      if (networkStatus.value === 'online') {
        measureNetworkLatency()
      }
    }, 5000)

    onUnmounted(() => {
      clearInterval(interval)
      if (animationFrame) {
        cancelAnimationFrame(animationFrame)
      }
    })
  })

  return {
    metrics: readonly(metrics),
    isLowPerformance: readonly(isLowPerformance)
  }
}

/**
 * 懒加载组合式函数
 */
export function useLazyLoad(callback: () => void, options: LazyLoadOptions = {}) {
  const {
    rootMargin = '50px',
    threshold = 0.1,
    once = true
  } = options

  const target = ref<HTMLElement | null>(null)
  const isVisible = ref(false)
  const isLoaded = ref(false)
  
  let observer: IntersectionObserver | null = null

  const observe = () => {
    if (!target.value || !('IntersectionObserver' in window)) {
      // 不支持IntersectionObserver时直接加载
      callback()
      isLoaded.value = true
      return
    }

    observer = new IntersectionObserver(
      (entries) => {
        const entry = entries[0]
        isVisible.value = entry.isIntersecting
        
        if (entry.isIntersecting && !isLoaded.value) {
          callback()
          isLoaded.value = true
          
          if (once) {
            observer?.disconnect()
          }
        }
      },
      {
        rootMargin,
        threshold
      }
    )

    observer.observe(target.value)
  }

  onMounted(() => {
    nextTick(observe)
  })

  onUnmounted(() => {
    observer?.disconnect()
  })

  return {
    target,
    isVisible: readonly(isVisible),
    isLoaded: readonly(isLoaded)
  }
}

/**
 * 图片懒加载专用函数
 */
export function useImageLazyLoad(src: string, options: LazyLoadOptions = {}) {
  const imageSrc = ref('')
  const imageLoaded = ref(false)
  const imageError = ref(false)

  const { target, isLoaded } = useLazyLoad(() => {
    loadImage()
  }, options)

  const loadImage = () => {
    const img = new Image()
    
    img.onload = () => {
      imageSrc.value = src
      imageLoaded.value = true
      imageError.value = false
    }
    
    img.onerror = () => {
      imageError.value = true
      imageLoaded.value = false
    }
    
    img.src = src
  }

  return {
    target,
    imageSrc: readonly(imageSrc),
    imageLoaded: readonly(imageLoaded),
    imageError: readonly(imageError),
    isLoaded: readonly(isLoaded)
  }
}

/**
 * 虚拟滚动组合式函数
 */
export function useVirtualScroll<T>(
  items: Ref<T[]>,
  itemHeight: number,
  containerHeight: number,
  buffer = 3
) {
  const scrollTop = ref(0)
  const containerRef = ref<HTMLElement | null>(null)

  const visibleRange = computed(() => {
    const start = Math.max(0, Math.floor(scrollTop.value / itemHeight) - buffer)
    const visibleCount = Math.ceil(containerHeight / itemHeight) + buffer * 2
    const end = Math.min(items.value.length, start + visibleCount)
    
    return { start, end }
  })

  const visibleItems = computed(() => {
    const { start, end } = visibleRange.value
    return items.value.slice(start, end).map((item, index) => ({
      item,
      index: start + index,
      top: (start + index) * itemHeight
    }))
  })

  const totalHeight = computed(() => items.value.length * itemHeight)
  
  const handleScroll = (e: Event) => {
    const target = e.target as HTMLElement
    scrollTop.value = target.scrollTop
  }

  onMounted(() => {
    containerRef.value?.addEventListener('scroll', handleScroll, { passive: true })
  })

  onUnmounted(() => {
    containerRef.value?.removeEventListener('scroll', handleScroll)
  })

  return {
    containerRef,
    visibleItems: readonly(visibleItems),
    totalHeight: readonly(totalHeight),
    scrollTop: readonly(scrollTop)
  }
}

/**
 * 防抖函数
 */
export function useDebounce<T extends (...args: any[]) => any>(
  fn: T,
  delay = 300
): [(...args: Parameters<T>) => void, () => void] {
  let timeoutId: NodeJS.Timeout | null = null

  const debouncedFn = (...args: Parameters<T>) => {
    if (timeoutId) {
      clearTimeout(timeoutId)
    }
    
    timeoutId = setTimeout(() => {
      fn(...args)
    }, delay)
  }

  const cancel = () => {
    if (timeoutId) {
      clearTimeout(timeoutId)
      timeoutId = null
    }
  }

  onUnmounted(() => {
    cancel()
  })

  return [debouncedFn, cancel]
}

/**
 * 节流函数
 */
export function useThrottle<T extends (...args: any[]) => any>(
  fn: T,
  delay = 300
): [(...args: Parameters<T>) => void, () => void] {
  let lastCall = 0
  let timeoutId: NodeJS.Timeout | null = null

  const throttledFn = (...args: Parameters<T>) => {
    const now = Date.now()
    
    if (now - lastCall >= delay) {
      lastCall = now
      fn(...args)
    } else {
      if (timeoutId) clearTimeout(timeoutId)
      
      timeoutId = setTimeout(() => {
        lastCall = Date.now()
        fn(...args)
      }, delay - (now - lastCall))
    }
  }

  const cancel = () => {
    if (timeoutId) {
      clearTimeout(timeoutId)
      timeoutId = null
    }
  }

  onUnmounted(() => {
    cancel()
  })

  return [throttledFn, cancel]
}

/**
 * 资源预加载
 */
export function usePreload() {
  const preloadedResources = new Set<string>()
  
  const preloadImage = (src: string): Promise<void> => {
    if (preloadedResources.has(src)) {
      return Promise.resolve()
    }
    
    return new Promise((resolve, reject) => {
      const img = new Image()
      img.onload = () => {
        preloadedResources.add(src)
        resolve()
      }
      img.onerror = reject
      img.src = src
    })
  }

  const preloadImages = async (srcs: string[]): Promise<void> => {
    const promises = srcs.map(src => preloadImage(src))
    await Promise.allSettled(promises)
  }

  const preloadScript = (src: string): Promise<void> => {
    if (preloadedResources.has(src)) {
      return Promise.resolve()
    }

    return new Promise((resolve, reject) => {
      const script = document.createElement('script')
      script.src = src
      script.onload = () => {
        preloadedResources.add(src)
        resolve()
      }
      script.onerror = reject
      document.head.appendChild(script)
    })
  }

  const preloadCSS = (href: string): Promise<void> => {
    if (preloadedResources.has(href)) {
      return Promise.resolve()
    }

    return new Promise((resolve, reject) => {
      const link = document.createElement('link')
      link.rel = 'stylesheet'
      link.href = href
      link.onload = () => {
        preloadedResources.add(href)
        resolve()
      }
      link.onerror = reject
      document.head.appendChild(link)
    })
  }

  return {
    preloadImage,
    preloadImages,
    preloadScript,
    preloadCSS,
    preloadedResources: readonly(preloadedResources)
  }
}

/**
 * 性能优化工具
 */
export const performanceUtils = {
  // 获取最优图片格式
  getOptimalImageFormat: (): 'webp' | 'avif' | 'jpeg' => {
    const canvas = document.createElement('canvas')
    
    if (canvas.toDataURL('image/avif').indexOf('image/avif') === 5) {
      return 'avif'
    } else if (canvas.toDataURL('image/webp').indexOf('image/webp') === 5) {
      return 'webp'
    } else {
      return 'jpeg'
    }
  },

  // 获取设备像素比优化的图片尺寸
  getOptimalImageSize: (width: number, height: number): { width: number; height: number } => {
    const dpr = window.devicePixelRatio || 1
    const maxDpr = 2 // 限制最大像素比以节省带宽
    
    const optimizedDpr = Math.min(dpr, maxDpr)
    
    return {
      width: Math.round(width * optimizedDpr),
      height: Math.round(height * optimizedDpr)
    }
  },

  // 检查是否应该启用低质量模式
  shouldUseLowQuality: (metrics: PerformanceMetrics): boolean => {
    return metrics.fps < 30 || 
           metrics.memoryUsage > 70 ||
           metrics.networkLatency > 500
  },

  // 动态调整图片质量
  getImageQuality: (connectionType: string): number => {
    switch (connectionType) {
      case 'slow-2g':
      case '2g': return 0.3
      case '3g': return 0.6
      case '4g': return 0.8
      default: return 0.9
    }
  }
}